/*
 * Copyright 2023-2024, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Haiku Development Team
 */

#include <KernelExport.h>

#include <arch/cpu.h>
#include <arch/int.h>
#include <boot/kernel_args.h>
#include <device_manager.h>
#include <kscheduler.h>
#include <interrupt_controller.h>
#include <smp.h>
#include <thread.h>
#include <timer.h>
#include <util/DoublyLinkedList.h>
#include <util/kernel_cpp.h>
#include <vm/vm.h>
#include <vm/vm_priv.h>
#include <vm/VMAddressSpace.h>

#include <string.h>

#include "arch_int_private.h"

// #define TRACE_ARCH_INT
#ifdef TRACE_ARCH_INT
#define TRACE(x) dprintf x
#else
#define TRACE(x) ;
#endif

// 定义LoongArch64异常向量表基址
#define LOONGARCH64_EXCEPTION_VECTOR_BASE 0x9000000000000000ULL

// 定义LoongArch64 CSR寄存器地址
#define CSR_CRMD 0x0   // 当前模式信息
#define CSR_PRMD 0x1   // 上一次模式信息
#define CSR_EUEN 0x2   // 扩展单元使能
#define CSR_MISC 0x3   // 杂项
#define CSR_ECFG 0x4   // 异常配置
#define CSR_ESTAT 0x5  // 异常状态
#define CSR_ERA 0x6    // 异常返回地址
#define CSR_BADV 0x7   // 异常访问地址
#define CSR_BADI 0x8   // 异常指令
#define CSR_EENTRY 0xc // 异常入口地址

// 定义LoongArch64异常类型
#define EXC_INT 0x0  // 中断
#define EXC_PIL 0x1  // 页无效例外（加载）
#define EXC_PIS 0x2  // 页无效例外（存储）
#define EXC_PIF 0x3  // 页无效例外（取指）
#define EXC_PME 0x4  // 页修改例外
#define EXC_PNR 0x5  // 页不可读例外
#define EXC_PNX 0x6  // 页不可执行例外
#define EXC_PPI 0x7  // 页特权等级不合规例外
#define EXC_ADEF 0x8 // 地址错例外（取指）
#define EXC_ADEM 0x9 // 地址错例外（内存）
#define EXC_ALE 0xa  // 地址未对齐例外
#define EXC_BCE 0xb  // 边界检查例外
#define EXC_SYS 0xc  // 系统调用例外
#define EXC_BRK 0xd  // 断点例外
#define EXC_INE 0xe  // 指令不存在例外
#define EXC_IPE 0xf  // 指令特权等级错例外
#define EXC_FPD 0x10 // 浮点禁用例外
#define EXC_FPE 0x11 // 浮点例外
#define EXC_DBP 0x12 // 调试例外（数据断点）
#define EXC_IBP 0x13 // 调试例外（指令断点）

// 中断控制器
static interrupt_controller_module_info *sInterruptControllerModule = NULL;
static interrupt_controller *sInterruptController = NULL;

// 中断处理程序表
static struct
{
    int_handler handler;
    void *data;
    int32 display_priority;
    const char *name;
} sLoongArch64InterruptHandlers[NUM_IO_INTERRUPTS];

// 中断嵌套计数
static int32 sLoongArch64InterruptNesting = 0;

// 初始化中断系统
status_t
arch_int_init(kernel_args *args)
{
    // 初始化中断处理程序表
    memset(sLoongArch64InterruptHandlers, 0, sizeof(sLoongArch64InterruptHandlers));

    // 初始化异常向量表
    init_exception_vectors();

    // 初始化中断控制器
    status_t status = init_interrupt_controller();
    if (status != B_OK)
        return status;

    return B_OK;
}

// 初始化每个CPU的中断
status_t
arch_int_init_post_vm(kernel_args *args)
{
    return B_OK;
}

// 初始化中断控制器后的设置
status_t
arch_int_init_post_device_manager(kernel_args *args)
{
    return B_OK;
}

// 启用中断
void arch_int_enable_interrupts(void)
{
    // 启用中断（设置CSR_CRMD的IE位）
    asm volatile(
        "csrrd $t0, %0\n"
        "ori $t0, $t0, 0x4\n" // 设置IE位
        "csrwr $t0, %0\n"
        :
        : "i"(CSR_CRMD)
        : "t0");
}

// 禁用中断
void arch_int_disable_interrupts(void)
{
    // 禁用中断（清除CSR_CRMD的IE位）
    asm volatile(
        "csrrd $t0, %0\n"
        "andi $t0, $t0, ~0x4\n" // 清除IE位
        "csrwr $t0, %0\n"
        :
        : "i"(CSR_CRMD)
        : "t0");
}

// 恢复中断状态
void arch_int_restore_interrupts(int oldState)
{
    if (oldState)
    {
        arch_int_enable_interrupts();
    }
    else
    {
        arch_int_disable_interrupts();
    }
}

// 获取中断状态
int arch_int_are_interrupts_enabled(void)
{
    uint32 crmd;
    asm volatile("csrrd %0, %1" : "=r"(crmd) : "i"(CSR_CRMD));
    return (crmd & 0x4) != 0;
}

// 发送处理器间中断
status_t
arch_smp_send_ici(int target_cpu)
{
    // 通过中断控制器发送IPI
    return sInterruptController->send_ipi(target_cpu);
}

// 发送广播处理器间中断
status_t
arch_smp_send_broadcast_ici(void)
{
    // 通过中断控制器发送广播IPI
    return sInterruptController->send_broadcast_ipi();
}
断控制器
static status_t
init_interrupt_controller(void)
{
    // 获取中断控制器模块
    status_t status = get_module(B_INTERRUPT_CONTROLLER_MODULE_NAME,
                                 (module_info **)&sInterruptControllerModule);
    if (status != B_OK)
    {
        dprintf("LoongArch64: Failed to get interrupt controller module: %s\n",
                strerror(status));
        return status;
    }

    // 获取中断控制器
    status = sInterruptControllerModule->get_interrupt_controller(&sInterruptController, 0);
    if (status != B_OK)
    {
        dprintf("LoongArch64: Failed to get interrupt controller: %s\n",
                strerror(status));
        return status;
    }

    return B_OK;
}

// 初始化异常向量表
static void
init_exception_vectors(void)
{
    // 设置异常入口地址
    asm volatile(
        "li.d $t0, %0\n"
        "csrwr $t0, %1\n"
        :
        : "i"(LOONGARCH64_EXCEPTION_VECTOR_BASE), "i"(CSR_EENTRY)
        : "t0");

    // 设置异常配置，启用所有异常
    asm volatile(
        "li.d $t0, 0xffffffffUL\n"
        "csrwr $t0, %0\n"
        :
        : "i"(CSR_ECFG)
        : "t0");
}

// 禁用中断
status_t
arch_int_disable_io_interrupt(int irq)
{
    if (irq < 0 || irq >= NUM_IO_INTERRUPTS)
        return B_BAD_VALUE;

    return sInterruptController->disable_io_interrupt(irq);
}

// 启用中断
status_t
arch_int_enable_io_interrupt(int irq)
{
    if (irq < 0 || irq >= NUM_IO_INTERRUPTS)
        return B_BAD_VALUE;

    return sInterruptController->enable_io_interrupt(irq);
}

// 分配中断
status_t
arch_int_map_io_interrupt(int irq, uint32 mode, cpu_mask_t *targetCPUs, bool allowNesting)
{
    if (irq < 0 || irq >= NUM_IO_INTERRUPTS)
        return B_BAD_VALUE;

    return sInterruptController->configure_io_interrupt(irq, mode, targetCPUs, allowNesting);
}

// 注册中断处理程序
status_t
arch_int_register_io_interrupt_handler(int irq, int_handler handler,
                                       void *data, const char *name, int32 displayPriority)
{
    // 检查参数
    if (irq < 0 || irq >= NUM_IO_INTERRUPTS)
        return B_BAD_VALUE;

    if (handler == NULL)
        return B_BAD_VALUE;

    // 检查是否已注册
    if (sLoongArch64InterruptHandlers[irq].handler != NULL)
        return B_BUSY;

    // 注册处理程序
    sLoongArch64InterruptHandlers[irq].handler = handler;
    sLoongArch64InterruptHandlers[irq].data = data;
    sLoongArch64InterruptHandlers[irq].display_priority = displayPriority;
    sLoongArch64InterruptHandlers[irq].name = name;

    return B_OK;
}

// 注销中断处理程序
status_t
arch_int_unregister_io_interrupt_handler(int irq, int_handler handler,
                                         void *data)
{
    // 检查参数
    if (irq < 0 || irq >= NUM_IO_INTERRUPTS)
        return B_BAD_VALUE;

    if (handler == NULL)
        return B_BAD_VALUE;

    // 检查是否匹配
    if (sLoongArch64InterruptHandlers[irq].handler != handler || sLoongArch64InterruptHandlers[irq].data != data)
    {
        return B_BAD_VALUE;
    }

    // 注销处理程序
    sLoongArch64InterruptHandlers[irq].handler = NULL;
    sLoongArch64InterruptHandlers[irq].data = NULL;
    sLoongArch64InterruptHandlers[irq].display_priority = 0;
    sLoongArch64InterruptHandlers[irq].name = NULL;

    return B_OK;
}

// 获取中断处理程序信息
status_t
arch_int_get_io_interrupt_handler_info(int32 index, io_interrupt_handler_info *info)
{
    if (index < 0 || index >= NUM_IO_INTERRUPTS)
        return B_BAD_VALUE;

    if (sLoongArch64InterruptHandlers[index].handler == NULL)
        return B_NO_INIT;

    info->irq = index;
    info->handler = sLoongArch64InterruptHandlers[index].handler;
    info->data = sLoongArch64InterruptHandlers[index].data;
    info->display_priority = sLoongArch64InterruptHandlers[index].display_priority;
    info->name = sLoongArch64InterruptHandlers[index].name;

    return B_OK;
}

// 中断处理函数
static void
loongarch64_handle_interrupt(int irq)
{
    if (irq < 0 || irq >= NUM_IO_INTERRUPTS)
        return;

    int_handler handler = sLoongArch64InterruptHandlers[irq].handler;
    void *data = sLoongArch64InterruptHandlers[irq].data;

    if (handler != NULL)
    {
        sLoongArch64InterruptNesting++;

        // 调用中断处理程序
        handler(data);

        sLoongArch64InterruptNesting--;
    }
    else
    {
        TRACE(("loongarch64_handle_interrupt: Unhandled interrupt: %d\n", irq));

        // 禁用未处理的中断
        arch_int_disable_io_interrupt(irq);
    }
}

// 异常处理函数
extern "C" void
loongarch64_exception_entry(iframe *frame)
{
    // 获取异常类型
    uint32 exceptionType;
    asm volatile("csrrd %0, %1" : "=r"(exceptionType) : "i"(CSR_ESTAT));
    exceptionType = (exceptionType >> 16) & 0x3f;

    switch (exceptionType)
    {
    case EXC_INT:
    {
        // 处理中断
        int irq = sInterruptController->acknowledge_io_interrupt();
        if (irq >= 0)
        {
            loongarch64_handle_interrupt(irq);
            sInterruptController->end_of_interrupt(irq);
        }
        break;
    }

    case EXC_SYS:
    {
        // 处理系统调用
        // 系统调用处理将在arch_syscall.cpp中实现
        frame->era += 4; // 跳过syscall指令
        break;
    }

    case EXC_BRK:
    {
        // 处理断点
        // 断点处理将在arch_debug.cpp中实现
        frame->era += 4; // 跳过break指令
        break;
    }

    case EXC_PIL:
    case EXC_PIS:
    case EXC_PIF:
    case EXC_PME:
    case EXC_PNR:
    case EXC_PNX:
    case EXC_PPI:
    {
        // 处理页错误
        // 页错误处理将在arch_vm.cpp中实现
        break;
    }

    default:
    {
        // 处理其他异常
            panic("Unhandled exception: %d, PC: %#lx\n", exceptionType,